package orchestration.android.execution.tasks;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import orchestration.android.RunExecutionActivity;
import orchestration.android.execution.exceptions.UnknownOperationException;
import orchestration.businessprocess.execution.Property;
import orchestration.persistence.exceptions.UnsupportedTypeException;
import orchestration.utils.PropertyUtils;
import android.database.Cursor;
import android.util.Log;

/**
 * @author  <a href="mailto:car.ferrarini@gmail.com">Carlo Ferrarini</a>
 */
public class SaveQueryResultOperation {
	
	public static final String OPERATION_GET_VALUE="getValue";
	public static final String OPERATION_GET_LINE="getLine";
	public static final String OPERATION_GET_COLUMN="getColumn";
	
	private static final String TAG="SaveQueryResultOperation";
	/**
	 * @uml.property  name="operation"
	 */
	private String operation;
	/**
	 * @uml.property  name="params"
	 */
	private String[] params;
	/**
	 * @uml.property  name="outputName"
	 */
	private String outputName;
	
	public SaveQueryResultOperation() {
		super();
		
	}
	
	/**
	 * @return
	 * @uml.property  name="operation"
	 */
	public String getOperation() {
		return operation;
	}

	/**
	 * @param operation
	 * @uml.property  name="operation"
	 */
	public void setOperation(String operation) {
		this.operation = operation;
	}

	/**
	 * @return
	 * @uml.property  name="params"
	 */
	public String[] getParams() {
		return params;
	}

	/**
	 * @param params
	 * @uml.property  name="params"
	 */
	public void setParams(String[] params) {
		this.params = params;
	}

	/**
	 * @return
	 * @uml.property  name="outputName"
	 */
	public String getOutputName() {
		return outputName;
	}

	/**
	 * @param outputName
	 * @uml.property  name="outputName"
	 */
	public void setOutputName(String outputName) {
		this.outputName = outputName;
	}

	public void exec(Cursor cursor, RunExecutionActivity rea) throws UnknownOperationException, UnsupportedTypeException{
		Property property = rea.getProperty(outputName);
		if(operation.equals(OPERATION_GET_VALUE)){
			int line= Integer.parseInt(params[0]);
			int column= cursor.getColumnIndex(params[1]);
			Log.i(TAG, "looking 4 column " +params[1] +", column index " + column);
				saveValue(cursor, line, column, property);
		}else if(operation.equals(OPERATION_GET_LINE)){
			int line= Integer.parseInt(params[0]);
			saveLine(cursor,line,property);
		}else if(operation.equals(OPERATION_GET_COLUMN)){
			int column= cursor.getColumnIndex(params[0]);
			saveColumn(cursor, column, property);
		}else
			throw new UnknownOperationException("operation " + operation + " is not a valid operation, valid ones are \"getValue(line,column)\",\"getLine(line)\",\"getColumn(columnName)\"");
		rea.saveProperty(property);
		
	}
	
	private static void saveValue(Cursor cursor,int line,int columnIndex,Property property) throws UnsupportedTypeException{
		if(cursor.moveToPosition(line)){
			if(columnIndex!=-1){
				String value= cursor.getString(columnIndex);
				Log.i(TAG,"trying to save" + value + "in property " + property.getName());
				PropertyUtils.setValueFromString(value, property,0);
			}
		}
	}
	@SuppressWarnings("unchecked")
	private static void saveLine(Cursor cursor,int line, Property property) throws UnsupportedTypeException{
			Object propValue;
			Class<?> propType = property.getType();
			cursor.moveToFirst();
			if(Map.class.isAssignableFrom(propType)){
				propValue= new HashMap();
				for(int i=0; i<cursor.getColumnCount();i++)
					((Map)propValue).put(cursor.getColumnName(i),cursor.getString(i));
			}else if(List.class.isAssignableFrom(propType)){
				propValue= new ArrayList();
				for(int i=0; i<cursor.getColumnCount();i++)
					((List)propValue).add(cursor.getString(i));
			}else if(propType.isArray()){
				Class<?> componentType=propType.getComponentType();
				propValue=Array.newInstance(componentType, cursor.getColumnCount());
				property.setValue(propValue);
				for(int i=0; i<cursor.getColumnCount();i++)
					PropertyUtils.setValueFromString(cursor.getString(i), property, i);
			}
	}
	
	@SuppressWarnings("unchecked")
	private static void saveColumn(Cursor cursor,int columnIndex,Property property) throws UnsupportedTypeException{
		Object propValue;
		Class<?> propType = property.getType();
		cursor.moveToFirst();
		if(List.class.isAssignableFrom(propType)){
			propValue= property.getValue();
			for(int i=0; i<cursor.getCount();i++) {
				((List)propValue).add(cursor.getString(columnIndex));
				cursor.moveToNext();
			}
		}else if(propType.isArray()){
			Class<?> componentType=propType.getComponentType();
			propValue=Array.newInstance(componentType, cursor.getColumnCount());
			property.setValue(propValue);
			for(int i=0; i<cursor.getCount();i++){
				PropertyUtils.setValueFromString(cursor.getString(columnIndex), property, i);
				cursor.moveToNext();
			}		
		}
	}
}
